home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
msysjour
/
vol06
/
05
/
iconex
/
iconex02.c
< prev
next >
Wrap
Text File
|
1991-09-01
|
53KB
|
1,666 lines
/*
* WINDOWS ICON EXTRACTION UTILITY - FILE READING FUNCTIONS
*
* LANGUAGE : Microsoft C 6.0
* TOOLKIT : Windows 3.0 SDK
* MODEL : Medium
* STATUS : Operational
*
* Copyright (C) 1991 - All Rights Reserved
*
* Eikon Systems, Inc.
* 989 East Hillsdale Blvd, Suite 260
* Foster City, California 94404
*
* 07/08/91 - James N. Hancock - initial creation.
*
*/
#include <windows.h>
#include <dos.h>
#include "iconex.h"
/* local defines */
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#define OF_ERROR -1
#define BITSPERBYTE 8
#define ICONHEADER_RESERVED 0
#define ICONHEADER_RESOURCETYPE 1
#define ICONTYPE_UNKNOWN 0
#define ICONTYPE_CGA 1
#define ICONTYPE_MONO 2
#define ICONTYPE_EGA 3
#define ICONTYPE_VGA 4
#define ICONTYPE_HIRES 5
#define MONO_PLANES 1
#define MONO_BITS 1
#define OS2EXE 1
#define WINDOWSEXE 2
#define OLDEXESIGNATURE 0x5A4D
#define NEWEXESIGNATURE 0x454E
#define ORDINALFLAG 0x8000
#define ICONRESTYPE 0x0003
#define GROUPICONRESTYPE 0x000E
/* local typedefs */
typedef struct { /* DOS 1, 2, 3, 4 .EXE header */
USHORT ehSignature; /* signature bytes */
USHORT ehcbLP; /* bytes on last page of file */
USHORT ehcp; /* pages in file */
USHORT ehcRelocation; /* count of relocation table entries*/
USHORT ehcParagraphHdr; /* size of header in paragraphs */
USHORT ehMinAlloc; /* minimum extra paragraphs needed */
USHORT ehMaxAlloc; /* maximum extra paragraphs needed */
USHORT ehSS; /* initial (relative) SS value */
USHORT ehSP; /* initial SP value */
USHORT ehChecksum; /* checksum */
USHORT ehIP; /* initial IP value */
USHORT ehCS; /* initial (relative) CS value */
USHORT ehlpRelocation; /* file address of relocation table */
USHORT ehOverlayNo; /* overlay number */
USHORT ehReserved[16]; /* reserved words */
LONG ehPosNewHdr; /* file address of new exe header */
} EXEHDR; /* eh */
typedef struct { /* new .EXE header */
WORD nhSignature; /* signature bytes */
CHAR nhVer; /* LINK version number */
CHAR nhRev; /* LINK revision number */
WORD nhoffEntryTable; /* offset of Entry Table */
WORD nhcbEntryTable; /* number of bytes in Entry Table */
LONG nhCRC; /* checksum of whole file */
WORD nhFlags; /* flag word */
WORD nhAutoData; /* automatic data segment number */
WORD nhHeap; /* initial heap allocation */
WORD nhStack; /* initial stack allocation */
LONG nhCSIP; /* initial CS:IP setting */
LONG nhSSSP; /* initial SS:SP setting */
WORD nhcSeg; /* count of file segments */
WORD nhcMod; /* entries in Module Reference Table*/
WORD nhcbNonResNameTable; /* size of non-resident name table */
WORD nhoffSegTable; /* offset of Segment Table */
WORD nhoffResourceTable; /* offset of Resource Table */
WORD nhoffResNameTable; /* offset of Resident Name Table */
WORD nhoffModRefTable; /* offset of Module Reference Table */
WORD nhoffImpNameTable; /* offset of Imported Names Table */
LONG nhoffNonResNameTable;/* offset of Non-resident Names Tab */
WORD nhcMovableEntries; /* count of movable entries */
WORD nhcAlign; /* segment alignment shift count */
WORD nhCRes; /* count of resource segments */
BYTE nhExeType; /* target OS (OS/2=1, Windows=2) */
BYTE nhFlagsOther; /* additional exe flags */
WORD nhGangStart; /* offset to gangload area */
WORD nhGangLength; /* length of gangload area */
WORD nhSwapArea; /* minimum code swap area size*/
WORD nhExpVer; /* expected Windows version number */
} NEWHDR; /* nh */
typedef struct { /* resource information block */
WORD rtType; /* resource type (icon = 3) */
WORD rtCount; /* number of resources of this type */
LONG rtProc; /* reserved for runtime use */
} RESTYPEINFO; /* rt */
typedef struct { /* Resource name information block */
USHORT rnOffset; /* file offset to resource data */
USHORT rnLength; /* length of resource data */
USHORT rnFlags; /* resource flags */
USHORT rnID; /* resource name id */
USHORT rnHandle; /* reserved for runtime use */
USHORT rnUsage; /* reserved for runtime use */
} RESNAMEINFO; /* rn */
typedef RESNAMEINFO FAR * LPRESNAMEINFO;
typedef struct {
RESTYPEINFO rt;
RESNAMEINFO rn[1];
} RESTABLE;
typedef RESTABLE FAR * LPRESTABLE;
/* The rnOffset and rnLength fields above must be shifted to compute their
* actual values. This allows resources to be larger than 64k, but they
* do not need to be aligned on 512 byte boundaries the way segments are.
*/
typedef struct {
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInRes;
WORD wNameOrdinal;
} RESDIRECTORY;
typedef struct {
BYTE fTypeFlag;
WORD wTypeOrdinal;
BYTE fNameFlag;
WORD wNameOrdinal;
WORD wMemoryFlags;
ULONG lSize;
} RESOURCEHEADER;
/* local prototypes */
static WORD GetIconType( BITMAPINFOHEADER* );
static HBITMAP GetANDBitmap( HDC, BYTE, BYTE, LPBYTE, LPBITMAPINFO, LONG );
static WORD GetBitmaps( HFILE, LPHANDLE, WORD, WORD, BYTE, BYTE, WORD,
WORD, LONG );
static BOOL GetXORDIBits( HDC, HBITMAP, LPBYTE, LPBITMAPINFO, LONG );
static HBITMAP GetXORBitmap( HDC, BYTE, BYTE, LPBYTE, LPBITMAPINFO, LONG );
static WORD ReadExeOldHeader( HFILE, LONG, PLONG );
static WORD ReadExeNewHeader( HFILE, LONG, LONG, PLONG );
static WORD ReadExeResTable( HFILE, LONG, PHANDLE );
static WORD ReadExeIcons( HFILE, LONG, HANDLE, WORD, LPWORD, LPHANDLE );
static HBITMAP CreateCFBITMAPData( ICON );
static HANDLE CreateCFSDKPAINTData( HBITMAP );
/*
*
* IconFree( hIconData ) : WORD;
*
* hIconData handle to aggregate icon data to free
*
* This function performs the cleanup for the icon extraction program. It
* frees the bitmaps of any icons that were read in from disk and frees
* the dynamic memory that was allocated for storing the ICON data
* structures.
*
* This function returns IDERR_SUCCESS if there are no errors, or a non-zero
* error code if there are.
*
*/
WORD FAR PASCAL IconFree(
HANDLE hIconData )
{
WORD wResult;
/* initialize */
wResult = IDERR_SUCCESS;
/* lock handle to icon data */
if (hIconData)
{
LPICONDATA lpIconData;
lpIconData = (LPICONDATA)GlobalLock( hIconData );
if (lpIconData)
{
WORD wArraySize;
WORD wIndex;
LPICON lpIconArray;
wArraySize = lpIconData->wArraySize;
lpIconArray = &(lpIconData->icIconArray[0]);
/* delete bitmaps that were created for icons */
for (wIndex = 0; wIndex < wArraySize; wIndex++)
{
if (lpIconArray[wIndex].hbmANDbits)
DeleteObject( lpIconArray[wIndex].hbmANDbits );
if (lpIconArray[wIndex].hbmXORbits)
DeleteObject( lpIconArray[wIndex].hbmXORbits );
}
/* free globally allocated memory */
if (GlobalUnlock( hIconData ) == 0)
GlobalFree( hIconData );
else
wResult = IDERR_LOCKFAIL;
} else
wResult = IDERR_LOCKFAIL;
} else
wResult = IDERR_INVALIDPARAM;
return wResult;
}
/*
*
* IconCreateIcon( hWnd, hIconData, wIndex, lphIcon ) : WORD;
*
* hWnd window handle of the window that is creating the icon
* hIconData handle to aggregate data structure
* wIndex index to the array element that is to be used
* lphIcon pointer to icon handle
*
* This function uses the information in an ICON data structure to create a
* Windows 3.0 icon through the CreateIcon function. It expects to receive a
* handle to an array of ICON data structures, plus an index to the element
* that is to be used to create the icon.
*
* This function returns IDERR_SUCCESS if there are no errors, or a non-zero
* error code if there are.
*
*/
#define BITSPERBYTE 8
WORD FAR PASCAL IconCreateIcon(
HWND hWnd,
HANDLE hIconData,
WORD wIndex,
LPHANDLE lphIcon )
{
WORD wResult;
HANDLE hXORbits;
HANDLE hANDbits;
LPBYTE lpbXORbits;
LPBYTE lpbANDbits;
HBITMAP hbmDestXORMask;
HBITMAP hbmDestANDMask;
WORD cbXORmaskSize;
WORD cbANDmaskSize;
WORD wIconWidth;
WORD wIconHeight;
ICON icIcon;
/* initialize */
wResult = IDERR_SUCCESS;
hXORbits = NULL;
hANDbits = NULL;
lpbXORbits = NULL;
lpbANDbits = NULL;
/* check parameters */
if (IsWindow( hWnd ) && hIconData)
{
LPICONDATA lpIconData;
lpIconData = (LPICONDATA)GlobalLock( hIconData );
if (lpIconData)
{
if (wIndex < lpIconData->wArraySize)
/* get icon creation data */
icIcon = lpIconData->icIconArray[wIndex];
else
wResult = IDERR_INVALIDPARAM;
GlobalUnlock( hIconData );
} else
wResult = IDERR_LOCKFAIL;
} else
wResult = IDERR_INVALIDPARAM;
/* create device dependent bitmaps for an icon on this system */
if (wResult == IDERR_SUCCESS)
{
HDC hdc;
HDC hdcSource;
HDC hdcDest;
hdc = GetDC( NULL );
if (hdc)
{
/* create device-dependent bitmaps for XOR mask and AND mask */
/* then use StretchBlt() to copy bits from ICON struct's bitmaps */
hdcSource = hdc ? CreateCompatibleDC( hdc ) : NULL;
hdcDest = hdc ? CreateCompatibleDC( hdc ) : NULL;
if (hdcSource && hdcDest)
{
/* get dimensions of an icon on this system */
wIconWidth = GetSystemMetrics( SM_CXICON );
wIconHeight = GetSystemMetrics( SM_CYICON );
/* create device-dependent bitmap for XOR mask */
hbmDestXORMask = CreateCompatibleBitmap( hdc,
wIconWidth,
wIconHeight
);
/* create device-dependent bitmap for monochrome AND mask */
hbmDestANDMask = CreateBitmap(
wIconWidth,
wIconHeight,
MONO_PLANES,
MONO_BITS,
NULL
);
if (hbmDestXORMask && hbmDestANDMask)
{
/* copy bits for XOR mask */
SelectObject( hdcSource, icIcon.hbmXORbits );
SelectObject( hdcDest, hbmDestXORMask );
SetStretchBltMode( hdcDest, COLORONCOLOR );
StretchBlt( hdcDest,
0, 0,
wIconWidth,
wIconHeight,
hdcSource,
0, 0,
icIcon.wWidth,
icIcon.wHeight,
SRCCOPY
);
/* copy bits for AND mask */
SelectObject( hdcSource, icIcon.hbmANDbits );
SelectObject( hdcDest, hbmDestANDMask );
SetStretchBltMode( hdcDest, BLACKONWHITE );
StretchBlt( hdcDest,
0, 0,
wIconWidth,
wIconHeight,
hdcSource,
0, 0,
icIcon.wWidth,
icIcon.wHeight,
SRCCOPY
);
} else {
wResult = IDERR_ALLOCFAIL;
}
DeleteDC( hdcSource );
DeleteDC( hdcDest );
} else {
wResult = IDERR_ALLOCFAIL;
}
ReleaseDC( NULL, hdc );
} else {
wResult = IDERR_ALLOCFAIL;
}
}
/* allocate memory where we can store device dependent XOR bits */
if (wResult == IDERR_SUCCESS)
{
BITMAP bm;
if (sizeof(BITMAP) == GetObject(
hbmDestXORMask,
sizeof(BITMAP),
(LPSTR)&bm ))
{
cbXORmaskSize = (bm.bmWidth * bm.bmHeight) *
(bm.bmPlanes * bm.bmBitsPixel) / BITSPERBYTE;
hXORbits = GlobalAlloc( GMEM_MOVEABLE, cbXORmaskSize );
if (hXORbits == NULL)
wResult = IDERR_ALLOCFAIL;
else if ((lpbXORbits = (LPBYTE)GlobalLock( hXORbits )) == NULL)
wResult = IDERR_LOCKFAIL;
else if (!GetBitmapBits( hbmDestXORMask,cbXORmaskSize,lpbXORbits))
wResult = IDERR_WINFUNCFAIL;
} else
wResult = IDERR_WINFUNCFAIL;
}
/* allocate memory where we can store AND bits */
if (wResult == IDERR_SUCCESS)
{
BITMAP bm;
if (sizeof(BITMAP) == GetObject(
hbmDestANDMask,
sizeof(BITMAP),
(LPSTR)&bm ))
{
cbANDmaskSize = (bm.bmWidth * bm.bmHeight) / BITSPERBYTE;
hANDbits = GlobalAlloc( GMEM_MOVEABLE, cbANDmaskSize );
if (hANDbits == NULL)
wResult = IDERR_ALLOCFAIL;
else if ((lpbANDbits = (LPBYTE) GlobalLock( hANDbits )) == NULL)
wResult = IDERR_LOCKFAIL;
else if (!GetBitmapBits( hbmDestANDMask,cbANDmaskSize,lpbANDbits))
wResult = IDERR_WINFUNCFAIL;
} else
wResult = IDERR_WINFUNCFAIL;
}
/* create the icon */
if (wResult == IDERR_SUCCESS)
{
HANDLE hInst;
BITMAP bm;
if (sizeof(BITMAP) == GetObject(
hbmDestXORMask,
sizeof(BITMAP),
(LPSTR)&bm ))
{
hInst = GetWindowWord( hWnd, GWW_HINSTANCE );
*lphIcon = CreateIcon(
hInst,
bm.bmWidth,
bm.bmHeight,
bm.bmPlanes,
bm.bmBitsPixel,
lpbANDbits,
lpbXORbits
);
}
if (*lphIcon == NULL)
wResult = IDERR_WINFUNCFAIL;
}
/* cleanup */
if (hXORbits)
{
if (lpbXORbits)
GlobalUnlock( hXORbits );
GlobalFree( hXORbits );
}
if (hANDbits)
{
if (lpbANDbits)
GlobalUnlock( hANDbits );
GlobalFree( hANDbits );
}
if (hbmDestXORMask)
DeleteObject(hbmDestXORMask);
if (hbmDestANDMask)
DeleteObject(hbmDestANDMask);
return wResult;
}
/*
*
* IconGetIconDescrip( hIconData, wIndex, lpszBuffer ) : WORD;
*
* hIconData handle to aggregate data structure
* wIndex index to the array element that is to be described
* lpszBuffer buffer for description
*
* This function returns IDERR_SUCCESS if there are no errors, or a non-zero
* error code if there are.
*
*/
WORD FAR PASCAL IconGetIconDescrip(
HANDLE hIconData,
WORD wIndex,
LPSZ lpszBuffer )
{
WORD wResult;
WORD wIconType;
LPICONDATA lpIconData;
LPSZ lpszDescrip;
/* initialize */
wResult = IDERR_SUCCESS;
lpIconData = NULL;
if (hIconData && lpszBuffer)
{
lpIconData = (LPICONDATA)GlobalLock( hIconData );
if (lpIconData)
{
if (wIndex < lpIconData->wArraySize)
{
/* determine icon type */
wIconType = lpIconData->icIconArray[wIndex].wIconType;
switch (wIconType)
{
case ICONTYPE_CGA:
lpszDescrip = "CGA Icon \r\n32x16, 2 Color";
break;
case ICONTYPE_MONO:
lpszDescrip = "MONO Icon \r\n32x32, 2 Color";
break;
case ICONTYPE_EGA:
case ICONTYPE_VGA:
lpszDescrip = "VGA / EGA Icon \r\n32x32, 16 Color";
break;
case ICONTYPE_HIRES:
lpszDescrip = "HI-RES Icon \r\n64x64, 16 Color";
break;
default:
lpszDescrip = "UNKNOWN ICON";
break;
}
lstrcpy( lpszBuffer, lpszDescrip );
} else
wResult = IDERR_INVALIDPARAM;
GlobalUnlock( hIconData );
} else
wResult = IDERR_LOCKFAIL;
} else
wResult = IDERR_INVALIDPARAM;
return wResult;
}
/*
* IconCopyToClipboard( hWnd, hIconData, wIndex, wPrivateFormat ) : WORD;
*
* hWnd window handle of the window that is making the copy
* hIconData handle to aggregate data structure
* wIndex index to the array element that is to be copied
* wPrivateFormat id of a private clipboard format to be used
*
* This function copies an icon to the clipboard using the SDKPAINT
* clipboard format.
*
* This function returns IDERR_SUCCESS if there are no errors, or a non-zero
* error code if there are.
*
*/
WORD FAR PASCAL IconCopyToClipboard(
HWND hWnd,
HANDLE hIconData,
WORD wIndex,
WORD wPrivateFormat )
{
WORD wResult;
LPICONDATA lpIconData;
ICON icIcon;
/* initialize */
wResult = IDERR_SUCCESS;
lpIconData = NULL;
if (IsWindow( hWnd ) && hIconData)
{
/* get the data for the icon to be copied */
lpIconData = (LPICONDATA)GlobalLock( hIconData );
if (lpIconData)
{
if (wIndex < lpIconData->wArraySize)
{
HBITMAP hbmCFBITMAP;
HANDLE hmemCFSDKPAINT;
icIcon = lpIconData->icIconArray[wIndex];
if (OpenClipboard( hWnd ))
{
hbmCFBITMAP = CreateCFBITMAPData( icIcon );
if (hbmCFBITMAP)
{
if ( EmptyClipboard() )
{
SetClipboardData( CF_BITMAP, hbmCFBITMAP );
hmemCFSDKPAINT=CreateCFSDKPAINTData(icIcon.hbmANDbits);
if (wPrivateFormat && hmemCFSDKPAINT)
SetClipboardData( wPrivateFormat, hmemCFSDKPAINT );
}
} else
wResult = IDERR_ALLOCFAIL;
if (! CloseClipboard())
wResult = IDERR_WINFUNCFAIL;
} else
wResult = IDERR_WINFUNCFAIL;
} else
wResult = IDERR_INVALIDPARAM;
GlobalUnlock( hIconData );
} else
wResult = IDERR_LOCKFAIL;
} else
wResult = IDERR_INVALIDPARAM;
return wResult;
}
/*
* CreateCFBITMAPData( icIcon ) : HBITMAP;
*
* icIcon structure containing icon dimensions and bitmap handles
*
* This function combines an icon's AND mask and XOR mask to create a bitmap
* that can be placed on the clipboard with the CF_BITMAP format.
*
* This function returns a bitmap handle if successful or NULL
* if unsuccessful.
*
*/
HBITMAP CreateCFBITMAPData(
ICON icIcon )
{
HBITMAP hbmResult;
HDC hdc;
/* init */
hbmResult = NULL;
/* get handle to device context */
hdc = GetDC( NULL );
if (hdc)
{
HDC hdcTarget;
HDC hdcSource;
HBRUSH hbrScreen;
hdcSource = CreateCompatibleDC( hdc );
if (hdcSource)
{
hdcTarget = CreateCompatibleDC( hdc );
if (hdcTarget)
{
hbrScreen = CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
if (hbrScreen)
{
/* create bitmap */
hbmResult = CreateCompatibleBitmap(
hdc,
icIcon.wWidth,
icIcon.wHeight
);
if (hbmResult)
{
/* STEP I : Fill rectangle with screen color */
SelectObject( hdcTarget, hbrScreen );
SelectObject( hdcTarget, hbmResult );
PatBlt(
hdcTarget,
0,
0,
icIcon.wWidth,
icIcon.wHeight,
PATCOPY
);
/* STEP II : Apply the AND mask */
SelectObject( hdcSource, icIcon.hbmANDbits );
BitBlt(
hdcTarget,
0, 0,
icIcon.wWidth,
icIcon.wHeight,
hdcSource,
0, 0,
SRCAND
);
/* STEP III : Copy the XOR mask */
SelectObject( hdcSource, icIcon.hbmXORbits );
BitBlt(
hdcTarget,
0, 0,
icIcon.wWidth,
icIcon.wHeight,
hdcSource,
0, 0,
SRCINVERT
);
}
DeleteObject( hbrScreen );
}
DeleteDC( hdcTarget );
}
DeleteDC( hdcSource );
}
ReleaseDC( NULL, hdc );
}
return hbmResult;
}
/*
* CreateCFSDKAPAINTData( hbmANDbits ) : HANDLE;
*
* hbmANDbits handle to bitmap for icon's AND mask
*
* This function allocates memory space and generates the SDK Paint private
* clipboard format. The SDKPAINT format must be registered with string
* "SDKPAINT" before use. The private SDKPAINT format data consists of:
*
* 1. a DWORD indicating the screen viewing color at the time image was
* sent to the clipboard followed by ...
* 2. the bits of the monochrome AND image in device dependent form.
*
* This function returns the memory handle if successful or NULL if not.
*
*/
HANDLE CreateCFSDKPAINTData(
HBITMAP hbmANDbits )
{
HANDLE hmemResult;
LONG lMemSize;
LONG lBMPSize;
LPDWORD lpdw;
BOOL fSuccess;
BITMAP bm;
/* initialize */
hmemResult = NULL;
fSuccess = TRUE;
if (GetObject( hbmANDbits, sizeof(BITMAP), (LPSTR)&bm )==sizeof(BITMAP))
{
/* compute memory size to allow for alignment on 16 byte boundary */
lBMPSize = ((((bm.bmHeight * bm.bmWidth) / 8) + 15) / 16) * 16;
lMemSize = sizeof( DWORD ) + lBMPSize;
/* allocate memory */
hmemResult = GlobalAlloc( GHND, lMemSize );
lpdw = hmemResult ? (LPDWORD) GlobalLock( hmemResult ) : NULL;
if (lpdw)
{
/* get current screen color */
*lpdw = GetSysColor( COLOR_WINDOW );
if (!GetBitmapBits(hbmANDbits,lBMPSize,(LPSTR)lpdw+sizeof(DWORD)))
fSuccess = FALSE;
}
else
fSuccess = FALSE;
}
else
fSuccess = FALSE;
/* unlock memory */
if (lpdw)
GlobalUnlock( hmemResult );
/* clean up if unsuccessful */
if (!fSuccess && hmemResult)
{
GlobalFree( hmemResult );
hmemResult = NULL;
}
return hmemResult;
}
/*
*
* IconExtract( lpszFileName, lphIconData, lpwIconCount ) : WORD;
*
* lpszFileName pointer to file name string
* lphIconData pointer to handle to aggregate icon data
* lpwCount pointer to variable in which to return icon count
*
* This function performs the following operations:
* - opens an .exe file
* - finds any component icons in the file
* - dynamically allocates an array of ICON data structures
* - fills the array of ICON data structures with all component icons
* - closes the file
*
* This function returns IDERR_SUCCESS if there are no errors, or a non-zero
* error code if there are.
*
* Notes: Icons in an .exe file are organized into groups. This function
* ignores the icon groups and simply reads the individual component icons
* from the file.
*
* References: MS-DOS Encyclopedia, pp. 119-124, pp. 1487-1491.
* Microsoft Windows Development Notes.
* Microsoft Windows 3.0 Internal Resource Formats (11/12/90)
*
*/
WORD FAR PASCAL IconExtract(
LPSZ lpszFileName,
LPHANDLE lphIconData,
LPWORD lpwIconCount )
{
HFILE hFile;
HANDLE haoff;
PWORD paoff;
WORD wResult;
WORD wShiftCount;
LONG lPos;
LONG lPosNewHdr;
LONG lPosResourceTable;
LONG lFileLen;
OFSTRUCT ofFile;
/* initialize */
wResult = IDERR_SUCCESS;
hFile = OF_ERROR;
haoff = NULL;
paoff = NULL;
*lpwIconCount = NULL;
*lphIconData = NULL;
/* open file for reading */
if ((hFile = OpenFile( lpszFileName, &ofFile, OF_READ)) == OF_ERROR)
wResult = IDERR_OPENFAIL;
/* get file length */
if (wResult == IDERR_SUCCESS)
if ((lFileLen = _llseek( hFile, 0L, SEEK_END )) == -1)
wResult = IDERR_READFAIL;
/* read old header, verify contents, and get positon of new header */
if (wResult == IDERR_SUCCESS)
wResult = ReadExeOldHeader( hFile, lFileLen, &lPosNewHdr );
/* read new header, verify contents, & get position of resource table */
if (wResult == IDERR_SUCCESS)
wResult = ReadExeNewHeader(
hFile,
lFileLen,
lPosNewHdr,
&lPosResourceTable
);
/* read shift count for file offsets of resources */
if (wResult == IDERR_SUCCESS)
{
USHORT cb;
/* initialize */
cb = 0;
lPos = _llseek( hFile, lPosResourceTable, SEEK_SET );
if (lPos == -1 || lPos > lFileLen || lPos != lPosResourceTable)
wResult = IDERR_READFAIL;
if (wResult == IDERR_SUCCESS)
cb = _lread( hFile, (LPSTR)&wShiftCount, sizeof(wShiftCount));
if (cb != sizeof(wShiftCount))
wResult = IDERR_READFAIL;
else if (wShiftCount > 16)
wResult = IDERR_RESTABLEBAD;
}
/* read resource table entries and save icon offsets */
if (wResult == IDERR_SUCCESS)
wResult = ReadExeResTable( hFile, lFileLen, &haoff );
/* read component icons from file */
if (wResult == IDERR_SUCCESS)
wResult = ReadExeIcons(
hFile,
lFileLen,
haoff,
wShiftCount,
lpwIconCount,
lphIconData
);
/* clean up */
if (haoff)
LocalFree( haoff );
if (hFile != OF_ERROR)
_lclose( hFile );
return wResult;
}
/*
*
* ReadExeOldHeader( hFile, lFileLen, plPosNewHdr ) : WORD;
*
* hFile file handle of .exe file being read
* lFileLen length of file
* plPosNewHdr pointer to file position of new header
*
* This function reads the old header from an executable file, checks to be
* sure that it is a valid header, and saves the position of the file's
* new header.
*
* This function returns IDERR_SUCCESS if there are no errors, or a non-zero
* error code if there are.
*
*/
WORD ReadExeOldHeader(
HFILE hFile,
LONG lFileLen,
PLONG plPosNewHdr )
{
LONG lPos;
USHORT cb;
EXEHDR ehOldHeader;
WORD wResult;
/* initialize */
wResult = IDERR_SUCCESS;
lPos = _llseek( hFile, 0L, SEEK_SET );
if (lPos == -1 || lPos != 0L)
wResult = IDERR_READFAIL;
if (wResult == IDERR_SUCCESS)
{
cb = _lread( hFile, (LPSTR)&ehOldHeader, sizeof(ehOldHeader) );
if (cb != sizeof(ehOldHeader))
wResult = IDERR_READFAIL;
else if (ehOldHeader.ehSignature != OLDEXESIGNATURE)
wResult = IDERR_FILETYPEBAD;
else if (ehOldHeader.ehPosNewHdr < sizeof(EXEHDR))
wResult = IDERR_EXETYPEBAD;
else if (ehOldHeader.ehPosNewHdr > lFileLen - sizeof(NEWHDR))
wResult = IDERR_EXETYPEBAD;
else
*plPosNewHdr = ehOldHeader.ehPosNewHdr;
}
return wResult;
}
/*
*
* ReadExeNewHeader( hFile, lFileLen, lPosNewHdr, plPosResourceTable ) : WORD;
*
* hFile file handle of .exe file being read
* lFileLen length of file
* lPosNewHdr file position of new header
* plPosResourceTable pointer to file position of resource table
*
* This function reads the new header from an executable file, checks to be
* sure that it is a valid header, and saves the position of the file's
* resource table.
*
* This function returns IDERR_SUCCESS if there are no errors, or a non-zero
* error code if there are.
*
*/
WORD ReadExeNewHeader(
HFILE hFile,
LONG lFileLen,
LONG lPosNewHdr,
PLONG plPosResourceTable )
{
WORD wResult;
USHORT cb;
LONG lPos;
NEWHDR nhNewHeader;
/* initialize */
wResult = IDERR_SUCCESS;
lPos = _llseek( hFile, lPosNewHdr, SEEK_SET );
if (lPos == -1 || lPos > lFileLen || lPos != lPosNewHdr)
wResult = IDERR_READFAIL;
else
{
WORD wVersion;
wVersion = (GetVersion() >> 8) | (GetVersion() << 8);
cb = _lread( hFile, (LPSTR)&nhNewHeader, sizeof(nhNewHeader) );
if (cb != sizeof(nhNewHeader))
wResult = IDERR_READFAIL;
else if (nhNewHeader.nhSignature != NEWEXESIGNATURE)
wResult = IDERR_FILETYPEBAD;
else if (nhNewHeader.nhExeType != WINDOWSEXE)
wResult = IDERR_EXETYPEBAD;
else if (nhNewHeader.nhExpVer < 0x0300)
wResult = IDERR_WINVERSIONBAD;
else if (nhNewHeader.nhExpVer > wVersion)
wResult = IDERR_WINVERSIONBAD;
else if (nhNewHeader.nhoffResourceTable == 0)
wResult = IDERR_RESTABLEBAD;
else
*plPosResourceTable = lPosNewHdr + nhNewHeader.nhoffResourceTable;
}
return wResult;
}
/*
*
* ReadExeResTable( hFile, lFileLen, phaoff ) : WORD;
*
* hFile file handle of .exe file being read
* lFileLen length of file
* phaoff address of variable to hold memory handle
*
* This function reads through the entries in an .exe file's resource table,
* identifies any icons in that table, and saves the file offsets of the data
* for those icons. This function expects the initial file position to point
* to the first entry in the resource table.
*
* This function returns IDERR_SUCCESS if there are no errors, or a non-zero
* error code if there are.
*
*/
WORD ReadExeResTable(
HFILE hFile,
LONG lFileLen,
PHANDLE phaoff )
{
HANDLE haoff;
BOOL fLoop;
WORD wResult;
WORD wLocalSize;
LONG lPosNextEntry;
USHORT iIcon;
/* initialize */
wResult = IDERR_SUCCESS;
fLoop = TRUE;
haoff = NULL;
iIcon = 0;
wLocalSize = 1;
lPosNextEntry = _llseek( hFile, 0L, SEEK_CUR );
/* loop through entries in resource table */
while (fLoop == TRUE)
{
USHORT cb;
USHORT iFile;
LONG lPos;
RESTYPEINFO rt;
PWORD paoff;
/* read RESTYPEINFO */
cb = _lread( hFile, (LPSTR)&rt, sizeof(rt) );
if (cb != sizeof(rt))
wResult = IDERR_READFAIL;
else if (rt.rtType != 0)
{
if (rt.rtType == (ORDINALFLAG | ICONRESTYPE))
{
wLocalSize += sizeof(WORD) * rt.rtCount;
haoff = (haoff == NULL) ?
LocalAlloc( LMEM_FIXED, wLocalSize ) :
LocalReAlloc( haoff, wLocalSize, LMEM_MOVEABLE );
if (haoff == NULL)
wResult = IDERR_ALLOCFAIL;
else if ((paoff = (PWORD)LocalLock( haoff )) == NULL)
wResult = IDERR_LOCKFAIL;
if (wResult == IDERR_SUCCESS)
{
for (
iFile = 0;
iFile<rt.rtCount && wResult==IDERR_SUCCESS;
iFile++)
{
RESNAMEINFO rn;
cb = _lread( hFile, (LPSTR)&rn, sizeof(rn) );
if (cb != sizeof(rn))
wResult = IDERR_READFAIL;
else
paoff[iIcon++] = rn.rnOffset;
}
/* mark end of list */
paoff[iIcon] = 0;
/* unlock memory */
LocalUnlock( haoff );
}
}
if (wResult == IDERR_SUCCESS)
{
lPosNextEntry += sizeof(rt) + rt.rtCount * sizeof(RESNAMEINFO);
lPos = _llseek( hFile, lPosNextEntry, SEEK_SET );
if (lPos == -1 || lPos > lFileLen || lPos != lPosNextEntry)
wResult = IDERR_READFAIL;
}
}
fLoop = (rt.rtType != 0) && (wResult == IDERR_SUCCESS);
}
if (wResult == IDERR_SUCCESS && iIcon == 0)
wResult = IDERR_NOICONS;
*phaoff = haoff;
/* return final result */
return wResult;
}
/*
*
* ReadExeIcons( hFile, lFileLen, haoff, wShiftCount, lpwIconCount,
* lphIconData ) : WORD;
*
* hFile file handle of .exe file being read
* lFileLen length of file
* haoff memory handle
* wShiftCount number of bits to shift file offsets
* lpwIconCount pointer to word containing the number of icons read
* lphIconData pointer to handle to aggregate icon data
*
* This function finds the icons in an .exe file, tests their DIB headers to
* determine if their type, and fills a data structure with their DDBs.
*
* This function returns IDERR_SUCCESS if there are no errors, or a non-zero
* error code if there are.
*
*/
WORD ReadExeIcons(
HFILE hFile,
LONG lFileLen,
HANDLE haoff,
WORD wShiftCount,
LPWORD lpwIconCount,
LPHANDLE lphIconData )
{
USHORT ioff;
USHORT iIcon;
WORD wResult;
PWORD paoff;
/* initialize */
wResult = IDERR_SUCCESS;
iIcon = 0;
/* lock local memory */
paoff = haoff ? (PWORD)LocalLock( haoff ) : NULL;
if (!paoff)
wResult = IDERR_LOCKFAIL;
/* loop through component icons */
for (ioff = 0; (paoff[ioff] != 0) && (wResult == IDERR_SUCCESS); ioff++)
{
BITMAPINFOHEADER bi;
LONG lPos;
LONG lPosDIB;
lPosDIB = (LONG)paoff[ioff] << wShiftCount;
lPos = _llseek( hFile, lPosDIB, SEEK_SET );
if (lPos == -1 || lPos > lFileLen || lPos != lPosDIB)
wResult = IDERR_READFAIL;
/* read BITMAPINFOHEADER */
if (wResult == IDERR_SUCCESS)
if (_lread( hFile, (LPSTR)&bi, sizeof(bi) ) != sizeof(bi))
wResult = IDERR_READFAIL;
/* build XOR and AND bitmaps */
if (wResult == IDERR_SUCCESS)
{
WORD wIconType;
wIconType = GetIconType( &bi );
if (wIconType != ICONTYPE_UNKNOWN)
{
WORD wColorTableSize;
WORD wDIBHeaderSize;
WORD wImageSize;
WORD wDIBSize;
/* calculate combined size of XOR & AND masks */
wImageSize = (WORD)(bi.biWidth * (bi.biHeight / 2)) *
(WORD)(bi.biBitCount + 1) / BITSPERBYTE;
/* calculate size of entire DIB */
wColorTableSize = sizeof(RGBQUAD) * (0x0001 << bi.biBitCount);
wDIBHeaderSize = (WORD)bi.biSize + wColorTableSize;
wDIBSize = wDIBHeaderSize + wImageSize;
wResult = GetBitmaps(
hFile,
lphIconData,
iIcon,
wIconType,
(BYTE)bi.biWidth,
(BYTE)(bi.biHeight / 2),
wDIBHeaderSize,
wDIBSize,
lPosDIB
);
iIcon++;
}
}
}
/* set error code if no icons found, or free memory if error occurred */
if (wResult == IDERR_SUCCESS)
{
if (iIcon == 0)
wResult = IDERR_NOICONS;
}
else
{
if (iIcon > 0)
{
IconFree( *lphIconData );
iIcon = 0;
}
}
*lpwIconCount = iIcon;
/* unlock memory */
if (paoff)
LocalUnlock( haoff );
/* return final result */
return wResult;
}
/*
* GetBitmaps( hFile, lphIconData, iIcon, wIconType, bWidth, bHeight,
* wDIBHeaderSize, wDIBSize, lPosDIB ) : WORD;
*
* hFile file handle
* lphIconData pointer to handle to aggregate icon data
* iIcon index to ICON array
* wIconType icon type identifer
* bWidth icon width
* bHeight icon height
* wDIBHeaderSize size of DIB header including color table
* wDIBSize device independent bitmap size
* lPosDIB file offset of the DIB
*
* This function computes XOR and AND mask bitmaps and fills the ICON data
* structure.
*
* This function returns IDERR_SUCCESS if there are no errors, or a non-zero
* error code if there are.
*
*/
WORD GetBitmaps(
HFILE hFile,
LPHANDLE lphIconData,
WORD iIcon,
WORD wIconType,
BYTE bWidth,
BYTE bHeight,
WORD wDIBHeaderSize,
WORD wDIBSize,
LONG lPosDIB )
{
LPSTR lpDIB;
HANDLE hMemDIB;
WORD wResult;
/* initialization */
wResult = IDERR_SUCCESS;
hMemDIB = NULL;
lpDIB = NULL;
/* allocate memory for the DIB */
if ((hMemDIB = GlobalAlloc( GMEM_MOVEABLE, wDIBSize )) == NULL)
wResult = IDERR_ALLOCFAIL;
else if ((lpDIB = GlobalLock( hMemDIB )) == NULL)
wResult = IDERR_LOCKFAIL;
/* read in device independent bitmaps for both the AND and XOR masks */
/* the file position is set, so that the BITMAPINFOHEADER is reread */
if (wResult == IDERR_SUCCESS)
if ((_llseek( hFile, lPosDIB, SEEK_SET ) != lPosDIB)
|| (WORD)(_lread( hFile, lpDIB, wDIBSize ) != wDIBSize))
wResult = IDERR_READFAIL;
/* create device-dependent bitmaps and copy DIB bits to them from the */
/* bits that were read in from disk */
if (wResult == IDERR_SUCCESS)
{
LPBITMAPINFO lpbmiXORinfo;
HDC hdc;
USHORT cbXORmaskSize;
USHORT cbANDmaskSize;
LPBYTE lpbDIBANDbits;
LPBYTE lpbDIBXORbits;
HBITMAP hbmXORbits;
HBITMAP hbmANDbits;
/* point to BITMAPINFO structure at beginning of DIB */
lpbmiXORinfo = (LPBITMAPINFO)lpDIB;
/* calculate mask sizes */
cbXORmaskSize = ((bWidth * bHeight) *
lpbmiXORinfo->bmiHeader.biBitCount) / BITSPERBYTE;
cbANDmaskSize = (bWidth * bHeight) / BITSPERBYTE;
/* calculate offsets to bitmap bits */
lpbDIBXORbits = lpDIB + wDIBHeaderSize;
lpbDIBANDbits = lpbDIBXORbits + cbXORmaskSize;
hdc = GetDC( NULL );
if (hdc)
{
lpbmiXORinfo->bmiHeader.biHeight = bHeight;
hbmXORbits = GetXORBitmap(
hdc,
bWidth,
bHeight,
lpbDIBXORbits,
lpbmiXORinfo,
cbXORmaskSize
);
if (hbmXORbits)
{
hbmANDbits = GetANDBitmap(
hdc,
bWidth,
bHeight,
lpbDIBANDbits,
lpbmiXORinfo,
cbANDmaskSize
);
/* allocate memory and fill out the ICON data structure */
if (hbmANDbits)
{
BITMAP bm;
USHORT cb;
cb = GetObject( hbmXORbits, sizeof(BITMAP), (LPSTR)&bm );
if (cb == sizeof(BITMAP))
{
HANDLE hIconData;
/* initialize */
hIconData = *lphIconData;
if (hIconData)
hIconData = GlobalReAlloc(
hIconData,
sizeof(ICONDATA) + (iIcon * sizeof(ICON)),
GMEM_MOVEABLE
);
else
hIconData = GlobalAlloc(
GMEM_MOVEABLE,
sizeof(ICONDATA)
);
if (hIconData)
{
LPICONDATA lpIconData;
*lphIconData = hIconData;
lpIconData = (LPICONDATA)GlobalLock( hIconData );
if (lpIconData)
{
ICON icTemp;
icTemp.wIconType = wIconType;
icTemp.wWidth = bm.bmWidth;
icTemp.wHeight = bm.bmHeight;
icTemp.bPlanes = bm.bmPlanes;
icTemp.bBitsPixel = bm.bmBitsPixel;
icTemp.hbmANDbits = hbmANDbits;
icTemp.hbmXORbits = hbmXORbits;
icTemp.lFilePos = lPosDIB;
lpIconData->wArraySize = iIcon + 1;
lpIconData->icIconArray[iIcon] = icTemp;
GlobalUnlock( hIconData );
} else
wResult = IDERR_LOCKFAIL;
} else
wResult = IDERR_ALLOCFAIL;
}
}
}
ReleaseDC( NULL, hdc );
} else {
wResult = IDERR_ALLOCFAIL;
}
if (wResult != IDERR_SUCCESS)
{
if (hbmXORbits)
DeleteObject( hbmXORbits );
if (hbmANDbits)
DeleteObject( hbmANDbits );
}
} /* end if (wResult == IDERR_SUCCESS) */
/* clean up */
if (hMemDIB)
{
if (lpDIB)
GlobalUnlock( hMemDIB );
GlobalFree( hMemDIB );
}
/* return value */
return wResult;
}
/*
* GetIconType( lpbi ) : WORD;
*
* lpbi points to BITMAPINFOHEADER component of DIB header
*
* This function checks the height, width, and color count of the specified
* DIB to determine if they match known icon types.
*
* This function returns a code identifying the icon type. It returns the value
* ICONTYPE_UNKNOWN if the icon type could not be determined.
*
*/
WORD GetIconType(
BITMAPINFOHEADER* lpbi )
{
typedef const struct {
WORD wIconType;
WORD wWidth;
WORD wHeight;
WORD wBitCount;
} ICONPARAMS;
WORD wResult;
WORD wIndex;
BITMAPINFOHEADER biTemp;
ICONPARAMS ip[] = {
{ICONTYPE_CGA, 32, 16, 1},
{ICONTYPE_MONO, 32, 32, 1},
{ICONTYPE_EGA, 32, 32, 4},
{ICONTYPE_VGA, 32, 32, 4},
{ICONTYPE_HIRES, 64, 64, 4},
{ICONTYPE_UNKNOWN, 0, 0, 0} };
/* initialize */
wResult = ICONTYPE_UNKNOWN;
biTemp = *lpbi;
/* check to see if current icon matches a known type */
for (wIndex = 0; wIndex < (sizeof(ip) / sizeof(ICONPARAMS)); wIndex++)
if ((biTemp.biWidth == ip[wIndex].wWidth) &&
(biTemp.biHeight == ip[wIndex].wHeight * 2) &&
(biTemp.biBitCount == ip[wIndex].wBitCount))
{
wResult = ip[wIndex].wIconType;
break;
}
/* return value */
return wResult;
}
/*
* GetXORBitmap( hdc, bWidth, bHeight, lpbBits, lpbmpInfo, lSize )
* : HBITMAP;
*
* hdc device context handle
* bWidth icon width
* bHeight icon height
* lpbBits bitmap bits
* lpbmpInfo pointer to BITMAPINFO struct
* lSize bitmap size
*
* This function creates an XOR mask bitmap.
*
* This function returns the handle to the bitmap if it is successful, or NULL
* if it fails.
*
*/
HBITMAP GetXORBitmap(
HDC hdc,
BYTE bWidth,
BYTE bHeight,
LPBYTE lpbBits,
LPBITMAPINFO lpbmpInfo,
LONG lSize )
{
HBITMAP hbmp;
/* create device-dependent bitmap for XOR mask */
hbmp = CreateCompatibleBitmap( hdc, bWidth, bHeight );
if (hbmp)
{
USHORT usScanLineCount;
/* modify BITMAPINFOHEADER structure for color bitmap */
lpbmpInfo->bmiHeader.biSizeImage = lSize;
/* convert XOR mask from DIB to device-dependent bitmap */
usScanLineCount = SetDIBits(
hdc,
hbmp,
0,
bHeight,
lpbBits,
lpbmpInfo,
DIB_RGB_COLORS
);
if (usScanLineCount == 0)
{
DeleteObject( hbmp );
hbmp = NULL;
}
}
/* return value */
return hbmp;
}
/*
* GetANDBitmap( hdc, bWidth, bHeight, lpbBits, lpbmpInfo, lSize ) : HBITMAP;
*
* hdc device context handle
* bWidth icon width
* bHeight icon height
* lpbBits bitmap bits
* lpbmpInfo pointer to BITMAPINFO struct
* lSize bitmap size
*
* This function creates an AND mask bitmap.
*
* This function returns the handle to the bitmap if it is successful, or NULL
* if it fails.
*
*/
HBITMAP GetANDBitmap(
HDC hdc,
BYTE bWidth,
BYTE bHeight,
LPBYTE lpbBits,
LPBITMAPINFO lpbmpInfo,
LONG lSize )
{
HBITMAP hbmp;
/* create device-dependent bitmap for AND mask */
hbmp = CreateBitmap( bWidth, bHeight, MONO_PLANES, MONO_BITS, NULL );
if (hbmp)
{
const RGBQUAD rBlack = { 0x00, 0x00, 0x00, 0x00 };
const RGBQUAD rWhite = { 0xFF, 0xFF, 0xFF, 0x00 };
USHORT usScanLineCount;
/* modify BITMAPINFOHEADER structure for monochrome bitmap */
lpbmpInfo->bmiHeader.biHeight = bHeight;
lpbmpInfo->bmiHeader.biSizeImage = lSize;
lpbmpInfo->bmiHeader.biBitCount = 1;
lpbmpInfo->bmiColors[0] = rBlack;
lpbmpInfo->bmiColors[1] = rWhite;
/* convert AND mask from DIB to device-dependent bitmap */
usScanLineCount = SetDIBits(
hdc,
hbmp,
0,
bHeight,
lpbBits,
lpbmpInfo,
DIB_RGB_COLORS
);
if (usScanLineCount == 0)
{
DeleteObject( hbmp );
hbmp = NULL;
}
}
/* return value */
return hbmp;
}